package ccb.ygqd.inspur.pin;


import android.content.Context;
import android.os.Bundle;

import com.siecomzg.constconfig.ErrorDefine;
import com.siecomzg.tool.LogUtil;
import com.siecomzg.transport.DeviceCallback;
import com.siecomzg.transport.SiecomDevice;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import ccb.ygqd.inspur.common.ConstHF;

/**
 * 密码键盘驱动类
 */
public class Pin  {

    private static  final String TAG = Pin.class.getSimpleName();
    private Context mContext ;
    public Pin(Context context){
        mContext = context;
    }

    /**
     *
     * @param iEncryType 默认值,DES加密方式；1-不加密 2-DES加密；3-3DES加密
     * @param iTimes 默认，一次；1-输入一次密码；2-输入二次密码
     * @param iLength 0,6-12 0-不限长度
     * @param iIndex  取值1-8,8组主密钥其中一组
     * @param strWorkKey 8字节长度的，经过主密钥加密的工作密钥
     * @param strTimeout 默认30秒
     * @return aryRet[0]为指示码，DRV0000000为正确，其它为错误码；
     * 如果aryRet[0]为DRV0000000，当iTimes=1时， aryRet[1]为返回的密码（2位密码长度+密码）；当iTimes=2时，aryRet[1]为空，aryRet[2]返回的密码（2位密码长度+密码）；
     */
    public String[] readPin(int iEncryType, final int iTimes, int iLength, int iIndex, String strWorkKey, String strTimeout){
        LogUtil.e(TAG,"readPin == " + "  " + iEncryType + " " +  iTimes + " " + iLength
                + " " + iIndex + " " + strWorkKey + " " + strTimeout);
        final String[] ret = new String[]{"","",""};
        if (!SiecomDevice.isConnected){
            ret[0] = ConstHF.ERR_NOT_CONN;
            ret[1] = ConstHF.ERR_DEV_ONT_CONN;
            ret[1] = "";
            return ret;
        }
        final CountDownLatch latch = new CountDownLatch(1);
        if (iIndex < 0) iIndex = 0;
        if (iIndex >= 6) iIndex = 5;
        final String keyId = iIndex + "";
        final int timeOut = Integer.parseInt(strTimeout);
        int voiceType = 0;
        if(iTimes == 2){
            voiceType = 1; //播放请再次输入密码
        }else
            voiceType = 0; //请输入密码

        int encrytType = 2; //加密类型 1 3DES  2 SM4  3 明文
        if (iEncryType == 1) encrytType = 3;
        if (iEncryType == 2 || iEncryType == 3) encrytType = 1;
        LogUtil.e(TAG,"encryptType == " + encrytType);
        iLength = (iLength <= 0 || iLength > 12) ? 12 : iLength;

        final int finalEncrytType = encrytType;
        final int finalILength = iLength;
        final int finalVoiceType = voiceType;
        SiecomDevice.inputWorkKey(keyId, keyId, strWorkKey, encrytType, 0x81, new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                latch.countDown();
                ret[0] = ConstHF.ERR_HARDWARE;
            }

            @Override
            public void onSuccess(Bundle bundle) {


                SiecomDevice.startInputPwd("000000000000", keyId, keyId, finalEncrytType, finalILength + "",
                        finalVoiceType, new DeviceCallback() {
                    @Override
                    public void onStart() {

                    }

                    @Override
                    public void onError(Bundle bundle) {
                        int code = bundle.getInt("code");
                        String msg = bundle.getString("message");
                        ret[1] = msg;
                        if (code == ErrorDefine.CANCEL_INPUT) {
                            ret[0] = ConstHF.ERR_USER_CANCEL;
                        }
                        if (code == ErrorDefine.KEY_TIME_OUT) {
                            ret[0] = ConstHF.ERR_TIME_OUT;
                        }
                        if (code == ErrorDefine.LENGTH_ERR) {
                            ret[0] = ConstHF.ERR_INVALID_OPERA;
                        }
                        if (code == ErrorDefine.SET_ENCRYPT_ERR) {
                            ret[0] = ConstHF.ERR_PIN_KEY_ERROR;
                        }
                        if (code == ErrorDefine.KEY_INPUT_ERR) {
                            ret[0] = ConstHF.ERR_PIN_KEY_ERROR;
                        }
                        latch.countDown();
                    }

                    @Override
                    public void onSuccess(Bundle bundle) {

                    }

                    @Override
                    public void onCompleted(Bundle bundle) {
                        String pwd = bundle.getString("data");
                        ret[0] = ConstHF.ERR_SUCCESS;

                        if (iTimes == 2){
                            ret[2] = String.format("%02d",pwd.length()) + pwd;
                        }else {
                            ret[1] = String.format("%02d",pwd.length()) + pwd;
                        }
                        latch.countDown();
                    }
                },timeOut * 1000,1,false);

            }

            @Override
            public void onCompleted(Bundle bundle) {

            }
        },timeOut,false);


        try {
            latch.await(timeOut + 2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return ret;
    }

    /**
     *
     * @param strRandom 12位，0-9之间的随机数字串
     * @param iLength 取值范围[0,6,7,8,9,10,11,12]，默认6
     * @param iKeyID 工作密钥的加密算法类型决定了采用何种加密算法加密PIN。
     * 用于加密密码的密钥会是SM4算法的密钥
     * @param strTimeout 默认30秒；
     * 其它正整数
     * @param iTimes 1-播放：“请输入密码”
     * 2 播放：“请再次输入密码”
     * @return
     */
    public String[] readPinEx(String strRandom, int iLength, int iKeyID, String strTimeout, final int iTimes){
        LogUtil.e(TAG,"Random == " + strRandom + " ---- iTimes == " + iTimes);
        final String[] ret = new String[]{"","",""};
        if (!SiecomDevice.isConnected){
            ret[0] = ConstHF.ERR_NOT_CONN;
            ret[1] = ConstHF.ERR_DEV_ONT_CONN;
            return ret;
        }
        final CountDownLatch latch = new CountDownLatch(1);
        if (iKeyID < 0) iKeyID = 0;
        if (iKeyID >= 6) iKeyID = 5;
        String keyId = iKeyID + "";
        int timeOut = Integer.parseInt(strTimeout);
        int voiceType = 0;
        if(iTimes == 2){
            voiceType = 1; //播放请再次输入密码
        }else
            voiceType = 0; //请输入密码

        iLength = (iLength <= 0 || iLength > 12) ? 12 : iLength;
        SiecomDevice.startInputPwd(strRandom, keyId, keyId, 2, iLength + "", voiceType, new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                int code = bundle.getInt("code");
                String msg = bundle.getString("message");
                if (code == ErrorDefine.CANCEL_INPUT) {
                    ret[0] = ConstHF.ERR_USER_CANCEL;
                }
                if (code == ErrorDefine.KEY_TIME_OUT) {
                    ret[0] = ConstHF.ERR_TIME_OUT;
                }
                if (code == ErrorDefine.LENGTH_ERR) {
                    ret[0] = ConstHF.ERR_INVALID_OPERA;
                }
                if (code == ErrorDefine.SET_ENCRYPT_ERR) {
                    ret[0] = ConstHF.ERR_PIN_KEY_ERROR;
                }
                if (code == ErrorDefine.KEY_INPUT_ERR) {
                    ret[0] = ConstHF.ERR_PIN_KEY_ERROR;

                }
                latch.countDown();
            }

            @Override
            public void onSuccess(Bundle bundle) {

            }

            @Override
            public void onCompleted(Bundle bundle) {
                String pwd = bundle.getString("data");
                ret[0] = ConstHF.ERR_SUCCESS;

//                if (iTimes == 2){
//                    ret[2] = String.format("%02d",pwd.length()) + pwd;
//                }else {
                    ret[1] =  pwd;
//                }

                latch.countDown();
            }
        },timeOut * 1000,1,false);

        try {
            latch.await(timeOut + 2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        for (int i = 0; i < ret.length; i++) {
            LogUtil.e(TAG,"----" + ret[i]);
        }

        return ret;
    }

    /**
     *
     * @param iAlgorithm 1：3DES密钥   2：SM4密钥
     * @param iKeyId 秘钥存放的索引位置
     * @param strKey 密钥数据，由byte[]转为16进制的字符串
     * @return DRV0000000为正确，其它为错误码
     */
    public String[] loadMainKey(int iAlgorithm, int iKeyId, String strKey){
        final String[] ret = new String[]{"","",""};
        if (!SiecomDevice.isConnected){
            ret[0] = ConstHF.ERR_NOT_CONN;
            ret[1] = ConstHF.ERR_DEV_ONT_CONN;
            return ret;
        }
        final CountDownLatch latch = new CountDownLatch(1);
        if (iKeyId < 0) iKeyId = 0;
        if (iKeyId >= 6) iKeyId = 5;
        String keyId = iKeyId + "";
        SiecomDevice.inputMainKey(keyId, strKey, iAlgorithm, 0, new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                ret[0] = ConstHF.ERR_HARDWARE;
                ret[1] = "设备故障，请尝试重启";
                latch.countDown();
            }

            @Override
            public void onSuccess(Bundle bundle) {
                ret[0] = ConstHF.ERR_SUCCESS;
                latch.countDown();
            }

            @Override
            public void onCompleted(Bundle bundle) {
                latch.countDown();
            }
        },10*1000,false);
        try {
            latch.await(11, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return ret;
    }

    /**
     *
     * @param iMainKeyId 标识工作密钥是使用哪一个主密钥加密的
     * @param iKeyType 0：多用途（以下3种用途均可）
     * 1: 计算MAC使用
     * 2：PIN加密使用
     * 3：加解密数据使用
     * @param iKeyId 工作秘钥存放的索引位置
     * @param strKey 密钥数据，由byte[]转为16进制的字符串
     * @return DRV0000000为正确，其它为错误码
     */
    public String[] loadWorkKey(int iMainKeyId, int iKeyType, int iKeyId, String strKey){
        final String[] ret = new String[]{"","",""};

        if (!SiecomDevice.isConnected){
            ret[0] = ConstHF.ERR_NOT_CONN;
            ret[1] = ConstHF.ERR_DEV_ONT_CONN;
            return ret;
        }
        final CountDownLatch latch = new CountDownLatch(1);
        if (iMainKeyId < 0) iMainKeyId = 0;
        if (iMainKeyId >= 6) iMainKeyId = 5;

        if (iKeyId < 0) iKeyId = 0;
        if (iKeyId >= 6) iKeyId = 5;
        String keyId = iKeyId + "";
        switch (iKeyType){
            case 1:
                iKeyType = 2;  // MAC key
                break;

            case 2:
                iKeyType = 1; // PIN key
                break;
            default:
                break;
        }
        SiecomDevice.inputWorkKey(iMainKeyId+"", keyId, strKey, 2,0x81,iKeyType, new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                ret[0] = ConstHF.ERR_HARDWARE;
                ret[1] = "设备故障，请尝试重启";
                latch.countDown();
            }

            @Override
            public void onSuccess(Bundle bundle) {
                ret[0] = ConstHF.ERR_SUCCESS;
                latch.countDown();
            }

            @Override
            public void onCompleted(Bundle bundle) {
                latch.countDown();
            }
        },10*1000,false);
        try {
            latch.await(11, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return ret;
    }

    /**
     * 对输入的数据利用指定的加密算法和秘钥进行加密/解密。
     * 本接口需要支持的输入数据，长度最长不超过4096字节。
     * @param strInput 待加密数据
     * 由byte[]转为16进制的字符串。
     * 待加密的数据长度最长不超过4096字节。
     * @param iMode 0：加密  1：解密
     * @param iKeyId 工作密钥的加密算法类别决定采用何种算法加解密数据。
     * @return  1 DRV0000000为正确，其它为错误码 2当返回成功时为16进制密文数据。当返回错误时为错误描述。
     */
    public String[] calculateData(String strInput, int iMode,int iKeyId){
        final String[] ret = new String[]{"","",""};
        if (!SiecomDevice.isConnected){
            ret[0] = ConstHF.ERR_NOT_CONN;
            ret[1] = ConstHF.ERR_DEV_ONT_CONN;
            return ret;
        }
        final CountDownLatch latch = new CountDownLatch(1);

        if (iKeyId < 0) iKeyId = 0;
        if (iKeyId >= 6) iKeyId = 5;

        String keyId = iKeyId + "";
        switch (iMode){
            case 0:
                iMode = 1;
                break;
            case 1:
                iMode = 0;
                break;
        }
        SiecomDevice.calculateData(iKeyId + "", strInput, iMode,2, 0,new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                ret[0] = ConstHF.ERR_PIN_KEY_ERROR;
                latch.countDown();
            }

            @Override
            public void onSuccess(Bundle bundle) {
                String outStr = "";
                try {
                    outStr = new JSONObject(bundle.getString("data")).getString("data");
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
                ret[0] = ConstHF.ERR_SUCCESS;
                ret[1] = outStr;
                latch.countDown();

            }

            @Override
            public void onCompleted(Bundle bundle) {

            }
        },10,false);
        try {
            latch.await(11, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return ret;
    }


    public String[] pinSmSupport(){
        String[] ret = new String[]{"","",""};
        ret[0] = ConstHF.ERR_SUCCESS;
        return ret;
    }


}
